/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.formserver.vmmanager.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.json.object.BizObjectSerializer;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.GspAssociationKeyCollection;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import com.inspur.edp.cef.designtime.api.element.GspAssociationKey;
import com.inspur.edp.cef.designtime.api.json.element.GspAssoKeyDeserializer;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.das.commonmodel.collection.GspElementCollection;
import com.inspur.edp.das.commonmodel.entity.element.GspCommonAssociation;
import com.inspur.edp.das.commonmodel.json.element.CmElementDeserializer;
import com.inspur.edp.das.commonmodel.json.element.GspCommonAssociationDeserializer;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.GspViewModelElement;
import com.inspur.edp.formserver.viewmodel.GspViewObject;
import com.inspur.edp.formserver.viewmodel.action.ViewModelDependentInfo;
import com.inspur.edp.formserver.viewmodel.common.ConvertUtils;
import com.inspur.edp.formserver.viewmodel.common.ViewModelMapping;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoElementMapping;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoElementSourceType;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoObjectSourceType;
import com.inspur.edp.formserver.viewmodel.exception.ViewModelException;
import com.inspur.edp.formserver.viewmodel.json.element.ViewElementDeserializer;
import com.inspur.edp.formserver.viewmodel.json.element.ViewElementSerializer;
import com.inspur.edp.formserver.viewmodel.json.mapping.GspVoElementMappingDeserializer;
import com.inspur.edp.formserver.viewmodel.json.mapping.GspVoElementMappingSerializer;
import com.inspur.edp.formserver.viewmodel.json.object.ViewObjectDeserializer;
import com.inspur.edp.formserver.viewmodel.json.object.ViewObjectSerializer;
import com.inspur.edp.formserver.viewmodel.util.ViewModelUtils;
import com.inspur.edp.formserver.vmmanager.exception.VoManagerErrorCodes;
import com.inspur.edp.formserver.vmmanager.util.CheckInfoUtil;
import com.inspur.edp.formserver.vmmanager.validate.model.ViewModelChecker;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.uri.MetadataURI;
import com.inspur.edp.lcm.metadata.api.exception.MetadataNotFoundException;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import io.iec.edp.caf.commons.exception.ExceptionLevel;
import io.iec.edp.caf.commons.utils.CollectionUtils;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import lombok.SneakyThrows;
import lombok.var;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.inspur.edp.formserver.viewmodel.common.ConvertUtils.toElement;

public class WebControllerService {
    public static WebControllerService getInstance() {
        return new WebControllerService();
    }

    public String getBizObject(GspBusinessEntity be, String objid) {
        IGspCommonObject bebject = be.getAllObjectList().stream().filter((item) -> item.getID().equals(objid)).findFirst().orElse(null);

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(IGspCommonDataType.class, new BizObjectSerializer());
        mapper.registerModule(module);
        try {
            return mapper.writeValueAsString(bebject);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0048, e);
        }
    }

    /**
     * 检查关键字
     *
     * @param jsonObject 视图对象Json结构
     */
    public void checkKeywords(String jsonObject) {
        if (jsonObject == null || jsonObject.isEmpty()) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0049, null);
        }
        ObjectMapper mapper = new ObjectMapper();
        GspViewModel viewModel;
        try {
            viewModel = mapper.readValue(jsonObject, GspViewModel.class);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0050, e);
        }
        ViewModelChecker.getInstance().check(viewModel);
    }

    /**
     * 获取虚拟vo关联
     *
     * @param info 待获取关联信息结构
     * @return 虚拟vo关联字段信息
     */
    public String getVirtualVoAsso(String info, EntityFunction func) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(info);
            String path = node.get("path").textValue();
            String refModelPkgName = null;
            if (!CheckInfoUtil.checkNull(node.get("refModelPkgName"))) {
                refModelPkgName = node.get("refModelPkgName").textValue();
            }
            String refModelId = node.get("refModelId").textValue();
            String voAssoJson = node.get("voAsso").textValue();
            String refElementIdsJson = node.get("refElementIds").textValue();
            String voElementLabelId = node.get("voElementLabelId").textValue();

            checkElementLabelId(voElementLabelId);

            var originVoAsso = readAsso(voAssoJson, new ViewElementDeserializer());
            var refElementIds = readIdList(refElementIdsJson);

            if (CollectionUtils.isEmpty(refElementIds)) {
                throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0051, null, ExceptionLevel.Error, false, voElementLabelId);
            }

            var originVoRefElements = originVoAsso.getRefElementCollection();
            ArrayList<IGspCommonElement> bizRefElements = func.getBizEntity(path, refModelPkgName, refModelId).getAllElementList(true);
            GspElementCollection refElements = new GspElementCollection(null);

            for (var refElementId : refElementIds) {
                IGspCommonElement voRefElement = (IGspCommonElement) originVoRefElements.stream().filter(item -> item.getRefElementId().equals(refElementId)).findFirst().orElse(null);
                if (!(voRefElement instanceof GspViewModelElement)) {
                    IGspCommonElement beRefElement = bizRefElements.stream().filter(item -> item
                            .getID().equals(refElementId)).findFirst().orElse(null);
                    if (!(beRefElement instanceof GspBizEntityElement)) {
                        throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0052, null, ExceptionLevel.Error, false, voElementLabelId, refElementId);
                    }
                    // 虚拟字段的关联带出字段也是虚拟字段
                    var newVoRefElement = getVirtualRefElement((GspBizEntityElement) beRefElement, voElementLabelId);
                    refElements.add(newVoRefElement);
                } else {
                    refElements.add(voRefElement);
                }
            }
            return writeViewElementsJson(refElements);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0053, e);
        }
    }

    public String getVirtualVoAsso(String info, boolean isRuntime) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(info);
            String path = node.get("path").textValue();
            String refModelPkgName = null;
            if (!CheckInfoUtil.checkNull(node.get("refModelPkgName"))) {
                refModelPkgName = node.get("refModelPkgName").textValue();
            }
            String refModelId = node.get("refModelId").textValue();
            String voAssoJson = node.get("voAsso").textValue();
            String refElementIdsJson = node.get("refElementIds").textValue();
            String voElementLabelId = node.get("voElementLabelId").textValue();

            checkElementLabelId(voElementLabelId);

            var originVoAsso = readAsso(voAssoJson, new ViewElementDeserializer());
            var refElementIds = readIdList(refElementIdsJson);

            if (CollectionUtils.isEmpty(refElementIds)) {
                throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0051, null, ExceptionLevel.Error, false, voElementLabelId);
            }

            var originVoRefElements = originVoAsso.getRefElementCollection();
            GspMetadata metadata = getMetadata(node, path, refModelPkgName, refModelId);
            GspBusinessEntity be = (GspBusinessEntity) metadata.getContent();
            ArrayList<IGspCommonElement> bizRefElements = be.getAllElementList(true);
            GspElementCollection refElements = new GspElementCollection(null);

            for (var refElementId : refElementIds) {
                IGspCommonElement voRefElement = (IGspCommonElement) originVoRefElements.stream().filter(item -> item.getRefElementId().equals(refElementId)).findFirst().orElse(null);
                if (!(voRefElement instanceof GspViewModelElement)) {
                    IGspCommonElement beRefElement = bizRefElements.stream().filter(item -> item
                            .getID().equals(refElementId)).findFirst().orElse(null);
                    if (!(beRefElement instanceof GspBizEntityElement)) {
                        throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0052, null, ExceptionLevel.Error, false, voElementLabelId, refElementId);
                    }
                    // 虚拟字段的关联带出字段也是虚拟字段
                    var newVoRefElement = getVirtualRefElement((GspBizEntityElement) beRefElement, voElementLabelId);
                    refElements.add(newVoRefElement);
                } else {
                    refElements.add(voRefElement);
                }
            }
            return writeViewElementsJson(refElements);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0053, e, ExceptionLevel.Error, false);
        }
    }

    private void checkElementLabelId(String voElementLabelId) {
        if (ViewModelUtils.checkNull(voElementLabelId) || ViewModelUtils.checkNull(voElementLabelId.trim())) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0101,null);
        } else {
            // LabelID在表单和报表中用作XML的标签，要限制非法字符
            String regex = "^[A-Za-z_][A-Za-z_\\d-.]*$";
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(voElementLabelId.trim());
            boolean isMatch = matcher.matches();
            if (!isMatch) {
                throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0102,null);
            }
        }
    }

    public GspCommonAssociation readAsso(String beAssoJson, CmElementDeserializer cmElementDeserializer) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        GspCommonAssociationDeserializer associationDeserializer = new GspCommonAssociationDeserializer(cmElementDeserializer);
        module.addDeserializer(GspAssociation.class, associationDeserializer);
        mapper.registerModule(module);
        try {
            GspCommonAssociation association = (GspCommonAssociation) mapper.readValue(beAssoJson, GspAssociation.class);
            return association;
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0056, e);
        }
    }

    public List<String> readIdList(String beEleIds) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(String.class, new StringDeserializer());
        mapper.registerModule(module);
        JavaType type = mapper.getTypeFactory().
                constructCollectionType(List.class, String.class);
        List<String> ids = null;
        try {
            ids = mapper.readValue(beEleIds, type);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0057, e);
        }
        return ids;
    }

    public GspViewModelElement getVirtualRefElement(GspBizEntityElement beElement, String voElementLabelId) {
        GspViewModelElement ele = ConvertUtils.toElement(beElement, null, null, GspVoElementSourceType.BeElement);
        ele.setID(UUID.randomUUID().toString());
        ele.setIsVirtual(true);
        ele.setIsVirtualViewElement(true);
        ele.setMapping(null);
        ele.setLabelID(voElementLabelId + "_" + beElement.getLabelID());
        ele.setIsRefElement(true);
        ele.setRefElementId(beElement.getID());
        // 20200319-关联带出字段必填应为false
        // Bug 305714: 字段非必填，关联出的字段必填，生成表单时显示关联出的字段不应该为必填
        ele.setIsRequire(false);
        if (ele.getHasAssociation()) {
            for (IGspCommonField item : ele.getChildAssociations().get(0).getRefElementCollection()) {
                ((GspViewModelElement) item).setIsVirtual(true);
                ((GspViewModelElement) item).setIsVirtualViewElement(true);
                ((GspViewModelElement) item).setMapping(null);
            }
        }
        return ele;
    }

    public String writeViewElementsJson(GspElementCollection voElements) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(IGspCommonField.class, new ViewElementSerializer());
        module.addDeserializer(IGspCommonField.class, new ViewElementDeserializer());
        mapper.registerModule(module);
        try {
            String vmJson = mapper.writeValueAsString(voElements);
            return vmJson;
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0058, e);
        }
    }

    public String convertBeElementIdsToVmElements(String convertEleInfo, EntityFunction func) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(convertEleInfo);
            String beEleIds = node.get("beEleIds").textValue();
            String bePkgName = null;
            if (!CheckInfoUtil.checkNull(node.get("bePkgName"))) {
                bePkgName = node.get("bePkgName").textValue();
            }

            String beId = node.get("beId").textValue();
            String objId = node.get("objId").textValue();
            List<String> beEleIdList = readIdList(beEleIds);

            GspBusinessEntity be = func.getBizEntity(null, bePkgName, beId);
            GspBizEntityObject obj = (GspBizEntityObject) be.findObjectById(objId);
            GspElementCollection voElements = convertPartialElementsToVoElements(obj, beEleIdList, bePkgName, beId,
                    GspVoElementSourceType.BeElement);
            return writeViewElementsJson(voElements);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(e);
        }
    }

    public String convertBeElementIdsToVmElements(String convertEleInfo, boolean isRuntime) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(convertEleInfo);
            String beEleIds = node.get("beEleIds").textValue();
            String bePkgName = null;
            if (!CheckInfoUtil.checkNull(node.get("bePkgName"))) {
                bePkgName = node.get("bePkgName").textValue();
            }

            String beId = node.get("beId").textValue();
            String objId = node.get("objId").textValue();
            List<String> beEleIdList = readIdList(beEleIds);

            GspMetadata metadata = getMetadata(node, null, bePkgName, beId);
            GspBusinessEntity be = (GspBusinessEntity) metadata.getContent();
            GspBizEntityObject obj = (GspBizEntityObject) be.findObjectById(objId);
            GspElementCollection voElements = convertPartialElementsToVoElements(obj, beEleIdList, bePkgName, beId,
                    GspVoElementSourceType.BeElement);
            return writeViewElementsJson(voElements);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0058, e, ExceptionLevel.Error, false);
        }
    }

    public String addBizObject(String addObjInfo, EntityFunction func) {
        ObjectMapper mapper = getViewObjectMapper();
        try {
            JsonNode node = mapper.readTree(addObjInfo);
            String keysJson = node.get("keysJson").textValue();
            String beId = node.get("beId").textValue();
            String bePkgName = null;
            if (!CheckInfoUtil.checkNull(node.get("bePkgName"))) {
                bePkgName = node.get("bePkgName").textValue();
            }
            String parentObjIDElementId = node.get("parentObjIDElementId").textValue();
            String bizObjCode = node.get("bizObjCode").textValue();


            // ①获取新增对象；
            GspBusinessEntity be = func.getBizEntity(null, null, beId);
            GspBizEntityObject bizObject = (GspBizEntityObject) be.findObjectByCode(bizObjCode);
            if (bizObject == null) {
                throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0059, null, ExceptionLevel.Error,
                        false, be.getCode(), be.getName(), bizObjCode);
            }
            bizObject.getKeys().clear();
            bizObject.getContainChildObjects().clear();
            var keys = readGspGspAssociationKeyCollection(keysJson);
            if (keys != null && keys.getCount() > 0) {
                for (GspAssociationKey key : keys) {
                    bizObject.getKeys().add(key);
                }
            }

            // ②转换为voObject
            GspViewObject newViewObject = ConvertUtils.toObject(bizObject, bePkgName, beId, parentObjIDElementId,
                    GspVoObjectSourceType.BeObject);

            return mapper.writeValueAsString(newViewObject);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0060, e);
        }
    }

    public String addBizObject(String addObjInfo, boolean isRuntime) {
        ObjectMapper mapper = getViewObjectMapper();
        try {
            JsonNode node = mapper.readTree(addObjInfo);
            String keysJson = node.get("keysJson").textValue();
            String beId = node.get("beId").textValue();
            String bePkgName = null;
            if (!CheckInfoUtil.checkNull(node.get("bePkgName"))) {
                bePkgName = node.get("bePkgName").textValue();
            }
            String parentObjIDElementId = node.get("parentObjIDElementId").textValue();
            String bizObjCode = node.get("bizObjCode").textValue();
            // ①获取新增对象；
            GspMetadata metadata = getMetadata(node, null, null, beId);
            GspBusinessEntity be = (GspBusinessEntity) metadata.getContent();
            GspBizEntityObject bizObject = (GspBizEntityObject) be.findObjectByCode(bizObjCode);
            if (bizObject == null) {
                throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0059, null,
                        ExceptionLevel.Error, false, be.getCode(), be.getName(), bizObjCode);
            }
            bizObject.getKeys().clear();
            bizObject.getContainChildObjects().clear();
            var keys = readGspGspAssociationKeyCollection(keysJson);
            if (keys != null && keys.getCount() > 0) {
                for (GspAssociationKey key : keys) {
                    bizObject.getKeys().add(key);
                }
            }

            // ②转换为voObject
            GspViewObject newViewObject = ConvertUtils.toObject(bizObject, bePkgName, beId, parentObjIDElementId,
                    GspVoObjectSourceType.BeObject);

            return mapper.writeValueAsString(newViewObject);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0060, e);
        }
    }

    private ObjectMapper getViewObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(IGspCommonDataType.class, new ViewObjectSerializer());
        module.addDeserializer(IGspCommonDataType.class, new ViewObjectDeserializer());
        mapper.registerModule(module);
        return mapper;
    }

    //TODO 此处需要确认
    private GspAssociationKeyCollection readGspGspAssociationKeyCollection(String keysJson) {

        GspAssociationKeyCollection keys = new GspAssociationKeyCollection();

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(GspAssociationKey.class, new GspAssoKeyDeserializer());
        mapper.registerModule(module);
        try {
            JsonNode nodeList = mapper.readTree(keysJson);
            if (nodeList.getNodeType() == JsonNodeType.ARRAY)
                for (JsonNode item : nodeList) {
                    keys.add(mapper.readValue(item.toString(), GspAssociationKey.class));
                }
        } catch (JsonProcessingException e) {
            throw new ViewModelException(e);
        }
        return keys;
    }

    private GspElementCollection convertPartialElementsToVoElements(IGspCommonObject co, List<String> eleIdList, String pkgName, String metaId, GspVoElementSourceType sourceType) {
        GspElementCollection voElements = new GspElementCollection(null);
        if (eleIdList != null && eleIdList.size() > 0) {
            for (String eleId : eleIdList) {
                GspBizEntityElement bizElement = (GspBizEntityElement) co.findElement(eleId);
                GspViewModelElement voElement = toElement(bizElement, pkgName, metaId, sourceType);
                voElement.getMapping().setTargetObjectId(co.getID());
                voElements.add(voElement);
            }
        }
        return voElements;
    }

    public GspVoElementMapping readVoEleMapping(String voEleMappingJson) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(ViewModelMapping.class, new GspVoElementMappingSerializer());
        module.addDeserializer(ViewModelMapping.class, new GspVoElementMappingDeserializer());
        mapper.registerModule(module);
        try {
            GspVoElementMapping voElemapping = (GspVoElementMapping) mapper.readValue(voEleMappingJson, ViewModelMapping.class);
            if (voElemapping == null) {
                throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0061, null, ExceptionLevel.Error, false);
            }
            return voElemapping;
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0062, e);
        }
    }

    public GspCommonAssociation getBizAsso(String path, GspVoElementMapping voEleMapping,
                                           String assoId, EntityFunction func) {
        GspBusinessEntity be = func.getBizEntity(path, voEleMapping.getTargetMetadataPkgName(), voEleMapping.getTargetMetadataId());
        String bizEleId = voEleMapping.getTargetElementId();
        GspBizEntityElement bizEle = (GspBizEntityElement) be.findElementById(bizEleId);
        if (bizEle == null) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0063, null, ExceptionLevel.Error, false, voEleMapping.getTargetMetadataId(), bizEleId);
        }
        if (bizEle.getChildAssociations().getCount() == 0) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0066, null, voEleMapping.getTargetMetadataId(), bizEleId);

        }
        GspAssociation association = bizEle.getChildAssociations().stream().filter(item -> item.getId().equals(assoId)).findFirst().orElse(null);
        if (!(association instanceof GspCommonAssociation)) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0065, null, voEleMapping.getTargetMetadataId(), bizEleId);
        }
        return (GspCommonAssociation) association;
    }

    public GspCommonAssociation getBizAsso(JsonNode node, String path, GspVoElementMapping voEleMapping,
                                           String assoId, boolean isRuntime) {
        GspMetadata metadata = getMetadata(node, path, voEleMapping.getTargetMetadataPkgName(), voEleMapping.getTargetMetadataId());
        GspBusinessEntity be = (GspBusinessEntity) metadata.getContent();
        String bizEleId = voEleMapping.getTargetElementId();
        GspBizEntityElement bizEle = (GspBizEntityElement) be.findElementById(bizEleId);
        if (bizEle == null) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0063, null, ExceptionLevel.Error, false, voEleMapping.getTargetMetadataId(), bizEleId);
        }
        if (bizEle.getChildAssociations().getCount() == 0) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0066, null, voEleMapping.getTargetMetadataId(), bizEleId);

        }
        GspAssociation association = bizEle.getChildAssociations().stream().filter(item -> item.getId().equals(assoId)).findFirst().orElse(null);
        if (!(association instanceof GspCommonAssociation)) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0065, null, voEleMapping.getTargetMetadataId(), bizEleId);
        }
        return (GspCommonAssociation) association;
    }

    public static GspMetadata getMetadata(JsonNode node, String path, String bePkgName, String beId) {
        if (ViewModelUtils.checkNull(beId)) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0067, null, false);
        }
        MetadataURI targetURI = new MetadataURI();
        targetURI.setId(beId);
        GspMetadata metadata;
        try {
            metadata = SpringBeanUtils.getBean(RefCommonService.class).getRefMetadata(targetURI, null, "");
        } catch (MetadataNotFoundException e) {
            if (node == null || CheckInfoUtil.checkNull(node.get("dependentInfo")))
                throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0068, null);
            else {
                String dependentInfo = node.get("dependentInfo").toString();
                ViewModelDependentInfo viewModelDependentInfo = getDependentInfo(dependentInfo);
                throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0069, null, viewModelDependentInfo.getCode(), viewModelDependentInfo.getName(), viewModelDependentInfo.getNameSpace());
            }
        }
        return metadata;
    }

    @SneakyThrows
    private static ViewModelDependentInfo getDependentInfo(String info) {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(info, ViewModelDependentInfo.class);
    }
}
